﻿#define _CRT_SECURE_NO_WARNINGS 1



#include <stdio.h>
//
//int main()
//{
//	int a = 10;
//	int b = a + 1;//b=11 a=10
//	int b = ++a;//b=11, a=11
//
//	return 0;
//}

//写一个宏，求两个数的较大值
/***************************************************************
* #define定义宏
#define 机制包括了⼀个规定，允许把参数替换到⽂本中，这种实现通常称为宏（macro）或定义宏（define macro）。
下⾯是宏的申明⽅式：
1 #define name( parament-list ) stuff
其中的 parament-list 是⼀个由逗号隔开的符号表，它们可能出现在stuff中。
注意：
参数列表的左括号必须与name紧邻，如果两者之间有任何空⽩存在，参数列表就会被解释为stuff的⼀部分。
****************************************************************/

/***************************************************************
*带有副作⽤的宏参数
当宏参数在宏的定义中出现超过⼀次的时候，如果参数带有副作⽤，那么你在使⽤这个宏的时候就可
能出现危险，导致不可预测的后果。副作⽤就是表达式求值的时候出现的永久性效果。
****************************************************************/
//#define MAX(x, y)  ((x)>(y)?(x):(y))//三目操作符
//
//int main()
//{
//	int a = 10;
//	int b = 20;
//	//int m = MAX(a++, b++);
//	int m = ((a++) > (b++) ? (a++) : (b++));
//	       //10    > 20    ?  x    :  21  
//	       // a=11 b=22
//	printf("%d\n", m);//?
//	printf("a=%d b=%d\n", a, b);
//
//	return 0;
//}

//#define MAX(x, y)  ((x)>(y)?(x):(y))
//
//int main()
//{
//	int a = 10;
//	int b = 5;
//	int m = MAX(a++, b++);
//	//int m = ((a++) > (b++) ? (a++) : (b++));
//	//10    > 20    ?  x    :  21  
//	// a=11 b=22
//	printf("%d\n", m);//?
//	printf("a=%d b=%d\n", a, b);
//
//	return 0;
//}


//#define M 100
//#define N M+2
//
//#define MAX(x, y)  ((x)>(y)?(x):(y))
//
//
//int main()
//{
//	int m = MAX(M, 15);
//	printf("MAX(M, 15)");
//
//	return 0;
//}

////宏
//#define MAX(x, y)  ((x)>(y)?(x):(y))
//
////函数
//int Max(int x, int y)
//{
//	return x > y ? x : y;
//}
//
//int main()
//{
//	int a = 10;
//	int b = 20;
//	//int m = MAX(3+5, b);
//	//int m = ((10) > (20) ? (10) : (20));
//	//printf("%d\n", m);
//
//	int m = Max(3+5, b);
//	printf("%d\n", m);
//
//	return 0;
//}
/***************************************************************
*用宏来自定义函数
* 宏有时候可以做函数做不到的事情。⽐如：宏的参数可以出现类型，但是函数做不到。
****************************************************************/

//#define MALLOC(n, type)    (type*)malloc(n*sizeof(type))
//
//int main()
//{
//	//int *p = (int*)malloc(10*sizeof(int));
//
//	int *p = MALLOC(10, int);//此时type 就是int的类型 用宏定义之后更加方便
//	//int* p = (int*)malloc(10 * sizeof(int));
//
//	return 0;
//}

/***************************************************************
*#和##
#运算符
#运算符将宏的⼀个参数转换为字符串字⾯量。它仅允许出现在带参数的宏的替换列表中。
#运算符所执⾏的操作可以理解为”字符串化“。
当我们有⼀个变量 int a = 10; 的时候，我们想打印出： the value of a is 10 .
就可以写：
1 #define PRINT(n) printf("the value of "#n " is %d", n);
当我们按照下⾯的⽅式调⽤的时候：
PRINT(a);//当我们把a替换到宏的体内时，就出现了#a，⽽#a就是转换为"a"，时⼀个字符串
代码就会被预处理为：
1 printf("the value of ""a" " is %d", a);
****************************************************************/


//void print(int n)
//{
//	printf("the value of n is %d\n", n);
//}

//#define PRINT(format, n)    printf("the value of " #n " is " format"\n", n)//#n里面的就是被转换的

//int main()
//{
//	int a = 10;
//	PRINT("%d", a);
//	//printf("the value of " "a" " is " "%d""\n", a);
//	//printf("the value of n is " "%d""\n", a);
//	//printf("the value of a is %d\n", a);
//
//	int b = 20;
//	PRINT("%d", b);
//	//printf("the value of b is %d\n", b);
//
//	float f = 5.5f;
//	PRINT("%f", f);
//	//printf("the value of " "f" " is " "%f""\n", f)
//	//printf("the value of n is " "%f""\n", f);
//	//printf("the value of f is %f\n", f);
//
//
//	return 0;
//}


//int main()
//{
//	printf("hello world\n");
//	printf("hello"" world\n");//分成两个双引号的内容也是可以连起来的
//
//	return 0;
//}

/***************************************************************
*## 运算符
## 可以把位于它两边的符号合成⼀个符号，它允许宏定义从分离的⽂本⽚段创建标识符。 ## 被称
为记号粘合
这样的连接必须产⽣⼀个合法的标识符。否则其结果就是未定义的
、命名约定
⼀般来讲函数的宏的使⽤语法很相似。所以语⾔本⾝没法帮我们区分⼆者。
那我们平时的⼀个习惯是：
把宏名全部⼤写
函数名不要全部⼤写
****************************************************************/
//生成函数的模板
//#define GENERIC_MAX(type) \   //宏定义来写一个函数 “\”是换行的意思 宏定义需要这样来写
//type type##_max(type x, type y)\
//{\
//	return x>y?x:y;\
//}
//
////使用上面的模板定义函数
////int_max
//GENERIC_MAX(int)  //替换到宏体内后int##_max ⽣成了新的符号 int_max做函数名
////float_max
//GENERIC_MAX(float)//替换到宏体内后float##_max ⽣成了新的符号 float_max做函数名
//
//int main()
//{
//	//
//	printf("%d\n", int_max(3, 5));//这里就直接可以调用新的符号使用函数
//	printf("%f\n", float_max(3.0, 5.0));
//
//	return 0;
//}

/***************************************************************
*#undef
这条指令⽤于移除⼀个宏定义。
****************************************************************/

//#define M 100
//
//int main()
//{
//	printf("%d\n", M);
//#undef M//此时这个地方的M宏定义就会被移除
//	printf("%d\n", M);
//
//	return 0;
//}


/***************************************************************
*条件编译
在编译⼀个程序的时候我们如果要将⼀条语句（⼀组语句）编译或者放弃是很⽅便的。因为我们有条
件编译指令。
⽐如说：
调试性的代码，删除可惜，保留⼜碍事，所以我们可以选择性的编译
****************************************************************/

#if 0 //为真1就编译   非0就不编 常量表达式
#define M 2

int main()
{
	printf("hehe\n");
	return 0;
}
#endif//结束

//int main()
//{
//	int a = 2;
//#if a==2 //err 用于常量 变量是错误的
//	printf("hehe");
//#endif
//	return 0;
//}


//多个分⽀的条件编译
//#define M 3
//int main()
//{
//#if M==1 //常量表达式
//	printf("hehe\n");
//#elif M==3 //常量表达式
//	printf("haha\n");
//#elif M == 4
//	printf("heihei\n");
//#else
//	printf("呵呵\n");
//#endif
//	return 0;
//}
//

//判断是否被定义
//#define zhangsan 100
//
//int main()
//{
//#if defined(zhangsan)//被定义了 上面的宏 此时就会编译下面代码
//	printf("zhangsan\n");
//#endif
//	return 0;
//}


//#define ZHANGSAN 100
//
//int main()
//{
//#ifdef ZHANGSAN //也可以直接这样写
//	printf("zhangsan\n");
//#endif
//	return 0;
//}
//
//

//#define ZHANGSAN 100

int main()
{
#ifndef ZHANGSAN //这里的意思是 判断是否没有定义ZHANGSAN 才为真 才会执行下面代码 也可以用#ifndef 把#if替换掉
#error	printf("zhangsan\n");
#endif
	return 0;
}


//宏定义的基本使用
//#include <stdio.h>

// #define M 100+200
// //呵呵
// int main()
// {

//     int a = M;
//     printf("hehe\n");
//     return 0;
// }

// int main()
// {
// 	printf("%s\n", __FILE__);
// 	printf("%d\n", __LINE__);
// 	printf("%s\n", __DATE__);
// 	printf("%s\n", __TIME__);
// 	printf("%d\n", __STDC__);//说明gcc完全遵循ANSI C

// 	return 0;
// }

// #define M 100
// #define STR "hehe"
// #define reg register

// int main()
// {
//     int arr[M] = {0};
//     int a = M;
//     printf("%d\n", M);
//     printf("%s\n", STR);
//     register int num = 0;
//     reg int num2 = 0;
//     return 0;
// }




// #define CASE break;case

// int main()
// {
// 	int n = 0;
// 	scanf("%d", &n);
// 	switch (n)
// 	{
// 	case 1:
// 		//
// 	CASE 2:
// 		//
// 	CASE 3:
// 		//..
// 	}
// 	return 0;
// }

//#define 定义符号的时候，最后不要加上分号
// #define M 100;

// int main()
// {
//     int a = M;
//     printf("%d\n", M);

//     int b = 0;
//     if(a>3)
//      b = M;
//     else
//      b = -1;

//     return 0;
// }


//实现一个宏，求平方

// #define SQUARE(n)  (n)*(n)

// int main()
// {
//     //int x = 0;
//     //scanf("%d", &x);
//     int ret = SQUARE(5+1);
//     printf("%d\n", ret);

//     return 0;
// }

//写一个代码求一个数的2倍
// #define DOUBLE(x) ((x)+(x))

// int main()
// {
//     int n = 0;
//     scanf("%d", &n);
//     int ret= DOUBLE(n);
//     printf("%d\n", ret);

//     ret = 10*DOUBLE(5);
//     printf("%d\n", ret);

//     return 0;
// }


/***************************************************************
*命令行编译
****************************************************************/

// int main()
// {
//     int arr[SZ] = {0};
//     int i = 0;
//     for(i=0; i<SZ; i++)
//     {
//         arr[i] = i+1;
//     }
//     for(i=0; i<SZ; i++)
//     {
//         printf("%d ", arr[i]);
//     }
//     return 0;
// }


// #define M 3

// int main()
// {
// #if M==2
// 	printf("hehe\n");
// #endif


// 	return 0;
// }

//#include "test.h"
//#include "test.h"
//#include "test.h"
//#include "test.h"
//#include "test.h"

int main()
{

    return 0;
}
//#define ZHANGSAN 100

//int main()
//{
//#ifndef ZHANGSAN
//	printf("zhangsan\n");
//#endif
//	return 0;
//}
//

//条件编译是为了跨平台性代码的编译


//#include "test.h"
//
//int main()
//{
//
//	return 0;
//}
/***************************************************
每个头⽂件的开头写：
#ifndef __TEST_H__
#define __TEST_H__
//头⽂件的内容
#endif //__TEST_H__
或者
1 #pragma once
就可以避免头⽂件的重复引⼊。
********************************************/